﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AppGene.DataModel
{
    /// <summary>
    /// The class provides converting functions.
    /// </summary>
    internal class LogicalDataTypeConvertor
    {
        /// <summary>
        /// Converts a type to a DbType.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>The DbType.</returns>
        /// <remarks>
        /// The converting rules:
        /// 4. Convert a type which is another logical table.
        /// </remarks>
        public static DbType ToDbType(Type type)
        {
            DbType toType;
            if (type.IsEnum)
            {
                if (MapTypeToDbType.TryGetValue(type.GetEnumUnderlyingType(), out toType))
                {
                    return toType;
                }
            }
            else if (MapTypeToDbType.TryGetValue(type, out toType))
            {
                return toType;
            }
            //TODO: Warning there is no matched type.
            return DbType.Object;
        }

        private static Dictionary<Type, DbType> mapTypeToDbType;
        /// <summary>
        /// The mapping from Type to DbType.
        /// </summary>
        private static Dictionary<Type, DbType> MapTypeToDbType
        {
            get
            {
                if (mapTypeToDbType == null)
                {
                    InitMapTypeToDbType();
                }
                return mapTypeToDbType;
            }
        }

        /// <summary>
        /// Initialize the map from Type to DbType. 
        /// </summary>
        private static void InitMapTypeToDbType()
        {
            mapTypeToDbType = new Dictionary<Type, DbType>();
            mapTypeToDbType.Add(typeof(bool), DbType.Boolean);
            mapTypeToDbType.Add(typeof(Byte), DbType.Byte);
            mapTypeToDbType.Add(typeof(Byte[]), DbType.Binary);
            mapTypeToDbType.Add(typeof(Char[]), DbType.String);
            mapTypeToDbType.Add(typeof(string), DbType.String);
            mapTypeToDbType.Add(typeof(DateTime), DbType.DateTime2);
            mapTypeToDbType.Add(typeof(DateTimeOffset), DbType.DateTimeOffset);
            mapTypeToDbType.Add(typeof(Decimal), DbType.Decimal);
            mapTypeToDbType.Add(typeof(double), DbType.Double);
            mapTypeToDbType.Add(typeof(Guid), DbType.Guid);
            mapTypeToDbType.Add(typeof(Int16), DbType.Int16);
            mapTypeToDbType.Add(typeof(Int32), DbType.Int32);
            mapTypeToDbType.Add(typeof(Int64), DbType.Int64);
            mapTypeToDbType.Add(typeof(Object), DbType.Object);
            mapTypeToDbType.Add(typeof(Single), DbType.Single);
            mapTypeToDbType.Add(typeof(TimeSpan), DbType.Time);
            mapTypeToDbType.Add(typeof(SByte), DbType.SByte);

        }
    }
}
